/*
 * bsp_ds18b20.c
 *
 *  Created on: Nov 19, 2020
 *      Author: kaijunHuang
 */

#include "bsp_ds18b20.h"

static uint8_t  fac_us=120;//us延时倍乘数
//延时nus
//nus为要延时的us数.
void delay_us(uint32_t nus)
{
	uint32_t ticks;
	uint32_t told,tnow,tcnt=0;
	uint32_t reload=SysTick->LOAD;	//LOAD的值
	ticks=nus*fac_us; 			//需要的节拍数
	tcnt=0;
	told=SysTick->VAL;        	//刚进入时的计数器值
	while(1)
	{
		tnow=SysTick->VAL;
		if(tnow!=told)
		{
			if(tnow<told)tcnt+=told-tnow;//这里注意一下SYSTICK是一个递减的计数器就可以了.
			else tcnt+=reload-tnow+told;
			told=tnow;
			if(tcnt>=ticks)break;//时间超过/等于要延迟的时间,则退出.
		}
	}
}
//延时nms
//nms:要延时的ms数
void delay_ms(uint16_t nms)
{
	delay_us((uint32_t)(nms*1000));	//普通方式延时,此时ucos无法启动调度.
}

//复位DS18B20
void DS18B20_Rst(void)
{
	DS18B20_IO_OUT(); //SET PA1 OUTPUT
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
	delay_us(750);    //拉低750us
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
	delay_us(15);     //15US
}
//等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在
uint8_t DS18B20_Check(void)
{
	uint8_t retry=0;
	DS18B20_IO_IN();//SET PA1 INPUT
	while (DS18B20_DQ_IN&&retry<200)
	{
		retry++;
		delay_us(1);
	}
	if(retry>=200)return 1;
	else retry=0;
	while (!DS18B20_DQ_IN&&retry<240)
	{
		retry++;
		delay_us(1);
	}
	if(retry>=240)return 1;
	return 0;
}
//从DS18B20读取一个位
//返回值：1/0
uint8_t DS18B20_Read_Bit(void) 			 // read one bit
{
	uint8_t data;
	DS18B20_IO_OUT();//SET PA1 OUTPUT
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
	delay_us(2);
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
	DS18B20_IO_IN();//SET PA1 INPUT
	delay_us(12);
	if(DS18B20_DQ_IN)
		data=1;
	else data=0;

	delay_us(50);

	return data;
}
//从DS18B20读取一个字节
//返回值：读到的数据
uint8_t DS18B20_Read_Byte(void)    // read one byte
{
	uint8_t i,j,dat;
	dat=0;
	for(i=1;i<=8;i++)
	{
		j=DS18B20_Read_Bit();
		dat=(j<<7)|(dat>>1);
	}

	return dat;
}
//写一个字节到DS18B20
//dat：要写入的字节
void DS18B20_Write_Byte(uint8_t dat)
{
	uint8_t j;
	uint8_t testb;
	DS18B20_IO_OUT();//SET PA1 OUTPUT;
	for (j=1;j<=8;j++)
	{
		testb=dat&0x01;
		dat=dat>>1;
		if (testb)
		{
			HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
			delay_us(2);
			HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
			delay_us(60);
		}
		else
		{
			HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
			delay_us(60);
			HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
			delay_us(2);
		}
	}
}
//开始温度转换
void DS18B20_Start(void)// ds1820 start convert
{
    DS18B20_Rst();
	DS18B20_Check();
    DS18B20_Write_Byte(0xcc);// skip rom
    DS18B20_Write_Byte(0x44);// convert
}
//初始化DS18B20的IO口 DQ 同时检测DS的存在
//返回1:不存在
//返回0:存在
//uint8_t DS18B20_Init(void)
//{
// 	GPIO_InitTypeDef GPIO_InitStruct;
//
// 	__HAL_RCC_GPIOA_CLK_ENABLE();
//
//
//	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
//	GPIO_InitStruct.Pin = GPIO_PIN_1;
//  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
//  GPIO_InitStruct.Pull = GPIO_NOPULL;
//  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
//  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

//	DS18B20_Rst();

//	return DS18B20_Check();
//}
//从ds18b20得到温度值
//精度：0.1C
//返回值：温度值 （-550~1250）
short DS18B20_Get_Temp(void)
{
    uint8_t temp;
    uint8_t TL,TH;
	short tem;
    DS18B20_Start();                    // ds1820 start convert
    DS18B20_Rst();
    DS18B20_Check();
    DS18B20_Write_Byte(0xcc);// skip rom
    DS18B20_Write_Byte(0xbe);// convert
    TL=DS18B20_Read_Byte(); // LSB
    TH=DS18B20_Read_Byte(); // MSB

    if(TH>7)
    {
        TH=~TH;
        TL=~TL;
        temp=0;//温度为负
    }else temp=1;//温度为正
    tem=TH; //获得高八位
    tem<<=8;
    tem+=TL;//获得底八位
    tem=(float)tem*0.625;//转换
	if(temp)return tem; //返回温度值
	else return -tem;
}
